#pragma once

#include <iostream>
#include <pthread.h>
#include <signal.h>
#include "Log.hpp"
#include "TcpServer.hpp"
#include "Task.hpp"
#include "ThreadPool.hpp"

#define PORT 8081

class HttpServer{
    private:
        int port;
        /*
         * 用于判断程序是否继续执行
         * */
        bool stop;
    public:
        HttpServer(int _port = PORT): port(_port),stop(false){}

        void InitServer(){
            //信号SIGPIPE需要进行忽略，如果不忽略，在写入时候，可能直接崩溃server
            signal(SIGPIPE, SIG_IGN); 
        }


        void Loop(){
            /*
             * 1.获取TcpServer实例
             * 2.循环获取TCP链接
             * 3.创建任务对象
             * 4.将任务对象push到对象当中， 继续下一步处理
             * */
            TcpServer *tsvr = TcpServer::getinstance(port);
            LOG(INFO, "Loop begin");
            while(!stop){
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);
                int sock = accept(tsvr->Sock(), (struct sockaddr*)&peer, &len);
                if(sock < 0){
                    continue;
                }
                LOG(INFO, "Get a new link");
                /*
                 * 创建任务对象， 这个任务对象， 最重要的就是将新连接的文件描述符传递给后台的工作线程进行处理
                 * 在这里的逻辑是， 创建的任务对象会被丢到线程池的线程安全队列当中， 由线程池的线程从队列当中POP后
                 * 进行处理， 从而将不同的HTTP请求分配给不同的线程来处理。
                 *
                 * 当前的是主线程， 主线程的工作
                 *    1.需要拿着侦听套接字进行侦听
                 *    2.任务对象push到线程的队列当中
                 * */
                Task task(sock);
                /*
                 * 线程池也是采用单例模式的方式
                 * */
                ThreadPool::getinstance()->PushTask(task);
            }
        }

        ~HttpServer(){}
};
